namespace C4F.DevKit.Bluetooth.ObjectPushProfile
{
    #region Using Directives
    using System.Collections.Generic;
    using System;
    using C4F.DevKit.Bluetooth.ObjectPushProfile.Resources;
    #endregion

    /// <summary>
    /// Abstract class to verify object types. This class should be implemented
    /// to create a type verifier.
    /// </summary>
    public abstract class ObjectTypeVerifier
    {
        #region Private Fields
        /// <summary>
        /// The list of objectTypes supported by the ObjectTypeVerifier.
        /// </summary>
        private List<string> objectTypes;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes the type verifier.
        /// </summary>
        protected ObjectTypeVerifier()
        {
            objectTypes = new List<string>();
        }
        #endregion

        #region Public Functions/Methods

        /// <summary>
        /// Overridable method for checking the type of the object received.
        /// All types that will be verified by this verifier should be added to
        /// the list of object types. This method should contain type checking
        /// code against all types mentioned in the list. If a type mismatch 
        /// occurs, an OPPTypeMismatchException should be thrown. In case the
        /// provided type is not supported, an ArgumentException should be 
        /// thrown.
        /// </summary>
        /// <param name="dataReceived">The byte array to be verified.</param>
        /// <param name="typeExpected">The type against which the passed object
        /// needs to be verified.</param>
        /// <exception cref="ArgumentException">The provided type is not present
        /// in the list of internally maintained object types.</exception>
        /// <exception cref="OPPTypeMismatchException">The type of data 
        /// received is not of the expected type.</exception>
        public abstract void VerifyType(byte[] dataReceived, string typeExpected);

        /// <summary>
        /// Returns true if the specified object type is present in the list of
        /// object types that will be verified when a call to VerifyType() is
        /// made.
        /// </summary>
        /// <param name="objectType">A string value whose existence is to be 
        /// checked in the list of object types supported by this type verifier.
        /// </param>
        /// <returns>A value indicating whether the object type is supported by
        /// the type verifier.</returns>
        /// <exception cref="ArgumentNullException">objectType is empty or
        /// passed as a null reference.</exception>
        public bool IsObjectTypeSupported(string objectType)
        {
            if (string.IsNullOrEmpty(objectType))
                throw new ArgumentNullException("objectType");

            if (this.objectTypes.Contains(objectType))
                return true;
            else
                return false;
        }

        #endregion

        #region Protected Functions/Methods

        /// <summary>
        /// Adds an object type to the list of object types that will be 
        /// verified when a call to VerifyType() is made.
        /// </summary>
        /// <param name="objectType">The object type to be added.</param>
        /// <exception cref="ArgumentNullException">objectType is empty or
        /// passed as a null reference.</exception>
        /// <exception cref="ArgumentException">objectType already exists in
        /// the internal list of object types supported by the type verifier.
        /// </exception>
        protected void AddObjectType(string objectType)
        {
            if (string.IsNullOrEmpty(objectType))
                throw new ArgumentNullException("objectType");

            if (this.objectTypes.Contains(objectType))
                throw new ArgumentException(OPPResources.Error_ObjectTypeExists,
                    "objectType");

            this.objectTypes.Add(objectType);
        }

        /// <summary>
        /// Removes an object type from the list of object types that will be
        /// verified when a call to VerifyType() is made.
        /// </summary>
        /// <param name="objectType">The object type to be removed.</param>
        /// <exception cref="ArgumentNullException">objectType is empty or
        /// passed as a null reference.</exception>
        /// <exception cref="ArgumentException">objectType does not exist in
        /// the internal list of object types supported by the type verifier.
        /// </exception>
        protected void RemoveObjectType(string objectType)
        {
            if (string.IsNullOrEmpty(objectType))
                throw new ArgumentNullException("objectType");

            if (!this.objectTypes.Contains(objectType))
                throw new ArgumentException(
                    OPPResources.Error_ObjectTypeDoesNotExist, "objectType");

            this.objectTypes.Remove(objectType);
        }

        /// <summary>
        /// Method for getting the object types that will be verified when a
        /// call to VerifyType() is made.
        /// </summary>
        /// <returns>String array of the object types supported by the type
        /// verifier.</returns>
        protected string[] GetSupportedObjectTypes()
        {
            return this.objectTypes.ToArray();
        }

        #endregion
    }
}